from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect, Http404
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
from django.template import RequestContext
from django.views.i18n import set_language as setlang

from lp.lpx.models import Project, Project_Data
from lp.lpx.myforms import ProjectForm, OptionsForm, ProfileForm, PasswordForm, LoginForm
from lp.lpx.myusers import get_user, is_anonymous, new_user
from lp.lpx.lplib import ULP

def index(request):
    from django.core.paginator import QuerySetPaginator, InvalidPage
    from lp.settings import LP
    template = 'index.html'
    step_name = 'home'
    projects = ''
    max_page = 7
    page = None
    webuser = get_user(request)
    anonym = is_anonymous(webuser)

    if not anonym:
        projects_all = QuerySetPaginator(webuser.project_set.order_by('-changed'), max_page)

        try:
            current = int(request.GET.get('page', '1'))
            page = projects_all.page(current)
            projects = page.object_list
        except InvalidPage:
            raise Http404
        
    return render_to_response(template, {
        'step_name' : step_name,
        'projects'  : projects,
        'page'      : page,
        'max_page'  : max_page,
        'LP'        : LP,
        'anonymous' : anonym,
    }, context_instance=RequestContext(request))

def step1(request, pid):
    template = 'step1.html'
    step_name = 'step1'
    error_msg = ''
    webuser = get_user(request)
    project = Project(user=webuser)


    if request.method == 'POST':
        if request.POST['submit_action'] == _('Next'):
            if request.session.test_cookie_worked():
                request.session.delete_test_cookie()
                if is_anonymous(webuser):
                    project = Project(user=new_user(request))

            step_form = ProjectForm(request.POST)
            if step_form.is_valid():
                try:
                    step_form.save_model(project)
                except:
                    error_msg = _('Error while saving project.')
                else:
                    return HttpResponseRedirect(reverse('lp.lpx.views.step2', args=[str(project.id)]))

    else:
        if pid == 'new':
            step_form = ProjectForm(initial={'proname': _('My project'),'objname': 'z', 'nonzero': True})
            if is_anonymous(webuser):
                request.session.set_test_cookie()

        else:
            try:
                project = webuser.project_set.get(pk=pid)
            except ObjectDoesNotExist:
                raise Http404
            else:
                step_form = ProjectForm(project.__dict__)

    return render_to_response(template, {
        'project'   : project,
        'step_name' : step_name,
        'step_form' : step_form,
        'error_msg' : error_msg,
    }, context_instance=RequestContext(request))

def step2(request, pid):
    step_name = 'step2'
    error_msg = ''
    viewtype = request.GET.get('view', 'classic')
    template = 'step2.html'
    webuser = get_user(request)

    if viewtype == 'flat':
        template = 'step2-flat.html'

    try:
        project = webuser.project_set.get(pk=pid)
    except ObjectDoesNotExist:
        raise Http404
    else:
        ulp = ULP(project)

    try:
        project_data = Project_Data.objects.get(pk=project)
        if not project_data.data:
            raise ObjectDoesNotExist
    except ObjectDoesNotExist:
        project_data = Project_Data(project=project)
        ulp.set_all_default()
    else:
        ulp.dict_to_data(project_data.data)

    if request.method == 'POST':
        if request.POST['submit_action'] == _('Next'):
            try:
                if viewtype == 'flat':
                    post = ulp.flat_to_post(request.POST)
                else:
                    post = request.POST
                project_data.data = ulp.post_to_dict(post)
                project_data.save()
            except ValueError:
                error_msg = _('Input Error (only integer and float numbers).')
            except:
                error_msg = _('Error while saving project data.')
                #TODO flat errors
            else:
                return HttpResponseRedirect(reverse('lp.lpx.views.step3', args=[str(project.id)]))

    return render_to_response(template, {
        'project'   : project,
        'step_name' : step_name,
        'ulp'       : ulp,
        'error_msg' : error_msg,
        'viewtype'  : viewtype,
    }, context_instance=RequestContext(request))

def step3(request, pid):
    template = 'step3.html'
    step_name = 'step3'
    webuser = get_user(request)
    error_msg = ''

    try:
        project = webuser.project_set.get(pk=pid)
        project_data = Project_Data.objects.get(pk=project)
        if not project_data.data:
            raise ObjectDoesNotExist
    except ObjectDoesNotExist:
        raise Http404

    if not project_data.options:
        step_form = OptionsForm(initial={'glpsol1': '--simplex', 'glpsol2': '--scale', 'simplex1': '--adv', 'simplex2': '--steep', 'simplex3': '--relax', 'simplex4': '--presol'})
    else:
        step_form = OptionsForm(project_data.options)

    if request.method == 'POST':
        if request.POST['submit_action'] == _('Solve'):
            step_form = OptionsForm(request.POST)
            if step_form.is_valid():
                try:
                    project_data.options = step_form.cleaned_data
                    project_data.save()
                except:
                    error_msg = _('Error while saving project options.')
                else:
                    return HttpResponseRedirect(reverse('lp.lpx.views.solve', args=[str(project.id)]))

    return render_to_response(template, {
        'project'   : project,
        'step_name' : step_name,
        'step_form' : step_form,
        'error_msg' : error_msg,
    }, context_instance=RequestContext(request))

def solve(request, pid):
    template = 'solve.html'
    step_name = 'solve'
    webuser = get_user(request)
    error_msg = ''
    success_msg = ''
    status = []
    tmpfiles = ''

    try:
        project = webuser.project_set.get(pk=pid)
        project_data = Project_Data.objects.get(pk=project)
        if not project_data.data or not project_data.options:
            raise ObjectDoesNotExist
    except ObjectDoesNotExist:
        raise Http404

    try:
        status.append(_('Loading project data'))
        ulp = ULP(project)
        ulp.dict_to_data(project_data.data)
    except:
        error_msg = _('Error while loading project data.')

    else:
        try: 
            status.append(_('Creating LP problem'))
            ulp.create_lp_problem()
        except: 
            error_msg = _('Error while creating LP problem.')

        else:
            try:
                status.append(_('Setting solver options'))
                ulp.set_solver_options(project_data.options)
            except: 
                error_msg = _('Error while processing solver options.')

            else:
                try:
                    status.append(_('Checking the LP problem'))
                    ulp.check_lp_problem()
                except OSError:
                    error_msg = _('Solver error while checking problem.')
                except StandardError:
                    error_msg = _('Model error (Problem has no columns).')
                except SystemError:
                    error_msg = _('Model error (problem model is not valid).')
                except:
                    error_msg = _('Unknow error while checking problem.')

                else:
                    try:
                        status.append(_('Solving the problem'))
                        solution = ulp.solve_lp_problem()
                    except OSError:
                        error_msg = _('Solver error while solving problem.')
                    except KeyError:
                        error_msg = _('Error while fetching status.')
                    except:
                        error_msg = _('Unknow error while solving problem.')

                    else:
                        try:
                            status.append(_('Saving problem solution'))
                            project_data.solution = solution
                            project_data.solfile = ulp.get_file(ulp.solfile)
                            project_data.bodfile = ulp.get_file(ulp.bodfile)
                            project_data.save()
                        except:
                            error_msg = _('Error while saving the solution')

    if not error_msg:
        status.append(_('Cleaning up'))
        ulp.clean_up()
        return HttpResponseRedirect(reverse('lp.lpx.views.solution', args=[str(project.id)]))

    if request.method == 'POST':
        if request.POST['submit_action'] == _('Report error'):
            ulp.clean_up(eval(request.POST['tmpfiles']))
            success_msg = _('Thank you.')

    return render_to_response(template, {
        'project'       : project,
        'step_name'     : step_name,
        'status'        : status,
        'error_msg'     : error_msg,
        'success_msg'   : success_msg,
        'tmpfiles'      : (ulp.modfile, ulp.solfile, ulp.bodfile, ulp.outfile),
    }, context_instance=RequestContext(request))

def solution(request, pid):
    template = 'solution.html'
    step_name = 'solution'
    webuser = get_user(request)

    try:
        project = webuser.project_set.get(pk=pid)
        project_data = Project_Data.objects.get(pk=project)
        if not project_data.data or not project_data.options or not project_data.solution:
            raise ObjectDoesNotExist
    except ObjectDoesNotExist:
        raise Http404

    solfile = { 'status' : request.GET.get('solfile', 'hide'),
                'content': project_data.solfile,
    }
    bodfile = { 'status' : request.GET.get('bodfile', 'hide'),
                'content': project_data.bodfile,
    }


    return render_to_response(template, {
        'project'   : project,
        'step_name' : step_name,
        'solution'  : project_data.solution,
        'solfile'   : solfile,
        'bodfile'   : bodfile,
    }, context_instance=RequestContext(request))

def delete(request, pid):
    template = 'delete.html'
    step_name = 'delete'
    webuser = get_user(request)
    error_msg = ''

    try:
        project = webuser.project_set.get(pk=pid)
    except ObjectDoesNotExist:
        raise Http404
    else:
        project.delete()

    return HttpResponseRedirect(reverse('lp.lpx.views.index'))

def settings(request, config):
    from django.utils.translation import ugettext_noop
    template    = "settings_" + config + ".html"
    step_name   = 'settings'
    configs     = (ugettext_noop('Language'), ugettext_noop('User'), ugettext_noop('Login'))
    error_msg   = ''
    success_msg = ''
    webuser     = get_user(request)

    profile_form    = ProfileForm(webuser.__dict__)
    password_form   = PasswordForm(webuser)
    login_form      = LoginForm()

    if request.method == 'POST':
        if request.POST['submit_action'] == _('Save'):
            profile_form = ProfileForm(request.POST)
            if profile_form.is_valid():
                try:
                    profile_form.save_model(webuser)
                except:
                    error_msg = _('Error while saving user data.')
                else:
                    success_msg = _('User profile was successfully updated.')

        if request.POST['submit_action'] == _('Set password'):
            password_form = PasswordForm(webuser, request.POST)
            if password_form.is_valid():
                try:
                    password_form.change_password()
                except:
                    error_msg = _('Error while setting your password.')
                else:
                    password_form = PasswordForm(webuser)
                    success_msg = _('Your password was successfully changed.')

        if request.POST['submit_action'] == _('Login'):
            login_form = LoginForm(request.POST)
            if login_form.is_valid():
                try:
                    webuser = login_form.authenticate()
                    if webuser is None:
                        raise SystemError
                    else:
                        from django.contrib.auth import login
                        login(request, webuser)
                except:
                    error_msg = _('Error. Incorrect username or password.')
                else:
                    return HttpResponseRedirect(reverse('lp.lpx.views.index'))

        if request.POST['submit_action'] == _('Logout'):
            from django.contrib.auth import logout
            logout(request)
            return HttpResponseRedirect(reverse('lp.lpx.views.settings', args=['login']))

    return render_to_response(template, {
        'step_name'     : step_name,
        'config_name'   : config,
        'config_items'  : configs,
        'error_msg'     : error_msg,
        'success_msg'   : success_msg,
        'password_form' : password_form,
        'profile_form'  : profile_form,
        'login_form'    : login_form,
        'anonymous'     : is_anonymous(webuser),
    }, context_instance=RequestContext(request))

def documentation(request, lang=None):
    if lang == None:
        lang = request.LANGUAGE_CODE
    template = 'documentation-' + str(lang) + '.html'
    step_name = 'documentation'

    return render_to_response(template, {
        'step_name' : step_name,
    }, context_instance=RequestContext(request))
